package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.api.content.model.dto.TeachplanMediaDTO;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.TeachPlanEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.agent.MediaApiAgent;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.TeachplanConvert;
import com.xuecheng.content.convert.TeachplanMediaConvert;
import com.xuecheng.content.entity.Teachplan;
import com.xuecheng.content.entity.TeachplanMedia;
import com.xuecheng.content.entity.ex.TeachplanNode;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.TeachplanMediaService;
import com.xuecheng.content.service.TeachplanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {

    @Autowired
    private CourseBaseService courseBaseService;


    @Autowired
    private MediaApiAgent mediaApiAgent;


    @Autowired
    private TeachplanMediaService teachplanMediaService;

    public TeachplanDTO queryTreeNodes(Long courseId, Long companyId) {
        courseBaseService.getCourseBaseById(courseId, companyId);
        // 根据courseId查询课程计划的树形结构
        TeachplanMapper teachplanMapper = this.getBaseMapper();
        List<TeachplanNode> nodes = teachplanMapper.selectTreeNodes(courseId);
        TeachplanDTO teachplanDTO = null;
        if (CollectionUtils.isEmpty(nodes)) {
            teachplanDTO = new TeachplanDTO();
        } else {
            // 通过list数据生成树形结构
            TeachplanNode rootNode = nodes.remove(0);
            generateTreeNodes(rootNode,nodes);
            // 将数据转为dto并返回
            teachplanDTO = TeachplanConvert.INSTANCE.node2dto(rootNode);
        }

        return teachplanDTO;
    }



    private void generateTreeNodes(TeachplanNode parentNode, List<TeachplanNode> nodes) {

        if (CollectionUtils.isEmpty(parentNode.getChildrenNodes())) {
            parentNode.setChildrenNodes(new ArrayList<>());
        }

        for (TeachplanNode node : nodes) {

            if (ObjectUtils.nullSafeEquals(parentNode.getId(),node.getParentid())) {
                parentNode.getChildrenNodes().add(node);


                Integer grade = node.getGrade();
                if (!(TeachPlanEnum.THIRD_LEVEL.equals(grade))) {
                    generateTreeNodes(node, nodes);
                } else {
                    // 判断三级课程计划是否有关联的 TeachplanMedia
                    LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(TeachplanMedia::getTeachplanId, node.getId());
                    queryWrapper.eq(TeachplanMedia::getCourseId, node.getCourseId());

                    TeachplanMedia teachplanMedia = teachplanMediaService.getOne(queryWrapper);

                    if (!(ObjectUtils.isEmpty(teachplanMedia))) {
                        node.setTeachplanMedia(teachplanMedia);
                    }
                    // 如果没有，不做操作
                }
            }

        }

    }

    @Transactional
    public TeachplanDTO createOrModifyTeachplan(TeachplanDTO dto, Long companyId) {

        //判断关键数据
        if (StringUtil.isBlank(dto.getPname())||
                ObjectUtils.isEmpty(dto.getCourseId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        // 判断业务操作
        TeachplanDTO resultDTO = null;
        Long teachPlanId = dto.getTeachPlanId();
        if (ObjectUtils.isEmpty(teachPlanId)) {
            // 新增
            resultDTO = createTeachplan(dto,companyId);

        } else {
            // 修改
            resultDTO = modifyTeachplan(dto,companyId);
        }


        // 3.返回teachplandto
        return resultDTO;
    }

    private TeachplanDTO createTeachplan(TeachplanDTO dto, Long companyId) {

        //判断业务数据
        CourseBaseDTO courseBase = courseBaseService.getCourseBaseById(dto.getCourseId(), companyId);
        // 给添加课程计划关联父级数据
        Teachplan parentNode = getParentNode(dto,courseBase);
        dto.setParentid(parentNode.getId());

        // 添加teachplan其他的数据

        dto.setGrade(parentNode.getGrade()+1);
        Long parentNodeId = parentNode.getId();
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getParentid, parentNodeId);
        int count = this.count(queryWrapper);
        dto.setOrderby(count+1);
        //保存课程计划数据
        Teachplan teachplan = TeachplanConvert.INSTANCE.dto2entity(dto);
        // 保证操作肯定是新增
        teachplan.setId(null);

        boolean result = this.save(teachplan);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120407);
        }
        //转换数据为dto并返回
        TeachplanDTO resultDTO = TeachplanConvert.INSTANCE.entity2dto(teachplan);


        return resultDTO;
    }

    private Teachplan getParentNode(TeachplanDTO dto, CourseBaseDTO courseBase) {
        //判断获得的是二级或三级课程计划父级数据
        Long parentid = dto.getParentid();
        if (ObjectUtils.isEmpty(parentid)) {
            // 获得二级课程计划的父级数据
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getParentid, TeachPlanEnum.FIRST_PARENTID_FLAG);
            queryWrapper.eq(Teachplan::getCourseId,courseBase.getCourseBaseId() );
            Teachplan firstNode = this.getOne(queryWrapper);
            if (ObjectUtils.isEmpty(firstNode)) {
                firstNode = new Teachplan();
                firstNode.setPname(courseBase.getName());
                firstNode.setParentid(new Long(TeachPlanEnum.FIRST_PARENTID_FLAG.toString()));
                firstNode.setGrade(TeachPlanEnum.FIRST_LEVEL);
                firstNode.setGrade(TeachPlanEnum.FIRST_LEVEL);
                firstNode.setOrderby(TeachPlanEnum.FIRST_LEVEL);
                firstNode.setCourseId(courseBase.getCourseBaseId());

                boolean result = this.save(firstNode);

                if (!result) {
                    ExceptionCast.cast(ContentErrorCode.E_120415);
                }
            }
            return firstNode;
        } else {
            // 获得三级课程计划的父级数据
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getId, parentid);
            Teachplan secNode = this.getOne(queryWrapper);
            if (ObjectUtils.isEmpty(secNode)) {
                ExceptionCast.cast(ContentErrorCode.E_120416);
            }
            return secNode;

        }
    }

    private TeachplanDTO modifyTeachplan(TeachplanDTO dto, Long companyId) {

        //判断关键数据
        Long courseId = dto.getCourseId();
        if (ObjectUtils.isEmpty(courseId)||
                StringUtil.isBlank(dto.getPname())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 判断业务数据
        courseBaseService.getCourseBaseById(courseId, companyId);
        // 课程计划
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getId, dto.getTeachPlanId());

        int count = this.count(queryWrapper);

        if (count < 1) {
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }
        // 修改课程计划数据:
        LambdaUpdateWrapper<Teachplan> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Teachplan::getPname, dto.getPname());
        updateWrapper.set(Teachplan::getMediaType, dto.getMediaType());
        updateWrapper.set(Teachplan::getStartTime, dto.getStartTime());
        updateWrapper.set(Teachplan::getEndTime, dto.getEndTime());
        updateWrapper.set(Teachplan::getDescription, dto.getDescription());
        updateWrapper.set(Teachplan::getIsPreview, dto.getIsPreview());
        updateWrapper.set(Teachplan::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(Teachplan::getId, dto.getTeachPlanId());

        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120407);
        }


        //  判断修改后的结果
        Teachplan teachplan = this.getById(dto.getTeachPlanId());
        TeachplanDTO resultDTO = TeachplanConvert.INSTANCE.entity2dto(teachplan);

        return resultDTO;
    }


    @Transactional
    public TeachplanMediaDTO associationMedia(TeachplanMediaDTO dto, Long companyId) {

        // 1.判断关键数据
        if (ObjectUtils.isEmpty(companyId)||
                ObjectUtils.isEmpty(dto.getTeachplanId())||
                ObjectUtils.isEmpty(dto.getMediaId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //  2.判断业务数据
        Teachplan teachplan = this.getById(dto.getTeachplanId());

        if (ObjectUtils.isEmpty(teachplan)) {
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }

        Integer grade = teachplan.getGrade();

        if (!(TeachPlanEnum.THIRD_LEVEL.equals(grade))) {
            ExceptionCast.cast(ContentErrorCode.E_120410);
        }

        //     2.2 课程基本信息
        Long courseId = teachplan.getCourseId();

        CourseBaseDTO courseBase= courseBaseService.getCourseBaseById(courseId, companyId);

        String auditStatus = courseBase.getAuditStatus();

        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //     2.3 媒资信息
        RestResponse<MediaDTO> restResponse = mediaApiAgent.getMediaById4s(dto.getMediaId());

        if (!(restResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(restResponse.getCode(),restResponse.getMsg());
        }

        MediaDTO media = restResponse.getResult();

        if (!(ObjectUtils.nullSafeEquals(companyId,media.getCompanyId()))) {
            ExceptionCast.cast(CommonErrorCode.E_403000);
        }

        String mediaAuditStatus = media.getAuditStatus();

        if (!(AuditEnum.AUDIT_PASTED_STATUS.getCode().equals(mediaAuditStatus))) {
            ExceptionCast.cast(ContentErrorCode.E_120417);
        }


        //  3.保存课程计划和媒资的关联信息
        LambdaQueryWrapper<TeachplanMedia> teachplanMediaQueryWrapper = new LambdaQueryWrapper<>();

        teachplanMediaQueryWrapper.eq(TeachplanMedia::getTeachplanId,teachplan.getId());
        teachplanMediaQueryWrapper.eq(TeachplanMedia::getCourseId,teachplan.getCourseId());

        int count = teachplanMediaService.count(teachplanMediaQueryWrapper);


        boolean result = false;
        if (count < 1) {
            TeachplanMedia teachplanMedia = new TeachplanMedia();

            teachplanMedia.setMediaId(media.getId());
            teachplanMedia.setTeachplanId(teachplan.getId());
            teachplanMedia.setCourseId(teachplan.getCourseId());
            teachplanMedia.setMediaFilename(media.getFilename());

            result = teachplanMediaService.save(teachplanMedia);
        } else {
            LambdaUpdateWrapper<TeachplanMedia> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(TeachplanMedia::getMediaId,media.getId());
            updateWrapper.set(TeachplanMedia::getMediaFilename,media.getFilename());

            updateWrapper.eq(TeachplanMedia::getTeachplanId, teachplan.getId());
            updateWrapper.eq(TeachplanMedia::getCourseId, teachplan.getCourseId());

            result = teachplanMediaService.update(updateWrapper);

        }


        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120411);
        }


        //  返回结果内容DTO
        TeachplanMedia po = teachplanMediaService.getOne(teachplanMediaQueryWrapper);

        TeachplanMediaDTO resultDTO = TeachplanMediaConvert.INSTANCE.entity2dto(po);

        return resultDTO;
    }



}
